🤔
- 性能优化是游戏项目开发过程中一个永恒的话题。玩家和项目的需求在并且会一直增长,同屏人数、游戏特效和场景复杂度永远在向着“榨干”硬件的趋势逼近。所以,无论硬件设备发展到何种程度,无论研发团队有多么丰富的经验积累,性能优化永远是一个非常棘手而又无法绕开的问题。
- 对于Unity性能优化,官方有非常好的教程,(参见官方教程)。如果英文水平一般,可以参考官方教程翻译
- 同时我们也可以去看看腾讯是如何做Unity手游性能优化的
- 这里我说一些自己的经验,以及常用的优化方法
工具
- 首先从Unity性能优化工具说起
- Unity Profile
Unity中最常用的官方性能分析工具,Unity Profiler能定量地找到C#的GC Alloc问题 XCode Capture GPU frame
能高效且定量地定位到GPU中shader的消耗。苹果平台下图形调试最好的选择。TimeProfiler
Instruments的TimeProfiler能高效且定量地定位C#脚本的CPU占用,甚至包括部分Unity引擎代码的CPU占用函数消耗,而不必麻烦地添加BeginSample()、EndSample()。
方法
- 性能优化主要是围绕CPU、GPU和内存三大方面进行,所以我们可以从这三方面展开。
CPU优化
- 使用对象池优化游戏物体的创建与销毁;
- 使用对象池时,应当可以支持把物体移除屏幕,连续使用的物体可以只是移出屏幕,只有长时间不使用的物体才隐藏;
- 减少对粒子系统Play()的调用;
- 避免实例化对象时造成cpu峰值。比如某一个特定时间,集中创建很多对象,这里可以使用协程做一些间隔;
- 尽量删除脚本中为空或不需要的方法;
- 同一脚本中频繁使用的变量建议声明其为全局变量,脚本之间频繁调用的变量或方法建议声明为全局静态变量或方法;
- 不要去频繁获取组件,将其声明为全局变量;
- 处理Rigidbody时,使用FixedUpdate,设置Fixed timestep,减少物理计算次数;
- 如果可以,尽量不用MeshCollider,如果不能避免的话,尽量用减少Mesh的面片数,或用较少面片的代理体来代替;
- 减少GetComponent()的使用频率,GetComponent()会有一定的GC产生,有少量的CPU消耗;
- 使用内建数组如使用Vector3.zero而不是new Vector(0,0,0);
GPU优化
- 保持材质的数目尽可能少;
- Mesh合并,可以在3dMax或其他建模软件上进行操作,也可在Unity中进行操作;
- 使用“全局光照+光照探头”代替实时局部光照;
- 避免使用实时阴影,如果必须使用实时阴影,可以在 Quality 质量设置中选择合适的阴影质量,在画面效果和渲染效率之间找到平衡点;
- LOD层级细节,根据距离的远近使用不同模型级别,这样就可以减少模型上面的顶点和面片数量从而提高性能;
- 使用纹理图集(一张大贴图里包含了很多子贴图)来代替一系列单独的小贴图;
- 使用遮挡剔除(Occlusion Culling)当场景中有大量模型需要渲染时,应用遮挡剔除可实现减少DrawCall提升性能的效果;
- Lightmapping光照贴图技术,首先将需要进行光照贴图的游戏物体设置为Lightmap Static,其次将用于光照贴图的所有光源设置为Baked模式,最后进行烘焙;
- 静态物体尽量将法线渲染到贴图。
- 使用静态批处理,静态批处理允许游戏引擎尽可能多的去降低绘制任意大小的物体所产生的DrawCall
内存优化
- 使用压缩纹理
- 及时释放资源
- 减少使用的库